gpNamespace.CardActions = cc.Class.extend({
    duiCount: 0,

    sort: function (tiles) {
        var currentT = null;
        var compareT = null;
        for (var i = 0; i < tiles.length; i++) {
            currentT = tiles[i];
            currentT.index = i;
            for (var j = i + 1; j < tiles.length; j++) {
                compareT = tiles[j];
                if (compareT != null && (currentT.num > compareT.num || (currentT.sprite && compareT.sprite && currentT.sprite.getLocalZOrder() > compareT.sprite.getLocalZOrder()))) {
//					cc.log("i:%d ,j:%d, type ：%s -> %s,num：%d -> %d" , i, j, currentT.type, compareT.type, currentT.num, compareT.num);
                    tiles[i] = compareT;
                    tiles[j] = currentT;
                    currentT = compareT;

                    currentT.index = i;
                }
            }
        }
    },

    generateComponent: function (tiles) {
        if (tiles == null || tiles.length == 0)
            return null;

        var tilesLength = tiles.length;
        if (tilesLength == 1)
            return new tyNamespace.Component(tyNamespace.ComponentType.Dan, tiles);

        var comps = this.generateAllComponents(tiles);

        var components;

        if (tilesLength % 2 == 0 && tilesLength / 2 <= 3) {
            components = comps.getComponents(tyNamespace.ComponentType.Zha);

            if (components.length >= 1) {
                var component = components[0];

                var remains = this.getRemains(tiles, component.tiles);

                if (remains.length == 0)
                    return component;
                else if (remains.length == 2) {
                	var siEr = new tyNamespace.Component(tyNamespace.ComponentType.SiEr, tiles);
                	siEr.setCore(component);

                	return siEr;
                } else if (remains.length == 4) {
                	var duiComps = this.toGenerateFullComponents(remains);

                	if (duiComps.getComponents(tyNamespace.ComponentType.Dui).length == 2) {
	                	var siEr = new tyNamespace.Component(tyNamespace.ComponentType.SiEr, tiles);
	                	siEr.setCore(component);
	
	                	return siEr;
                	}
                }
            }
        }

        if (tilesLength == 2) {
            components = comps.getComponents(tyNamespace.ComponentType.Dui);
            if (components.length == 1)
                return components[0];
        }

        if (tilesLength % 2 == 0 && tilesLength >= 6) {
            components = comps.getComponents(tyNamespace.ComponentType.ErShun);

            if (components.length >= 1) {
                var component = components[0];

                var remains = this.getRemains(tiles, component.tiles);

                if (remains.length == 0)
                    return component;
            }
        }

        if (tilesLength >= 5) {
            components = comps.getComponents(tyNamespace.ComponentType.Shun);

            if (components.length >= 1) {
                var component = components[0];
                var remains = this.getRemains(tiles, component.tiles);

                if (remains.length == 0)
                    return component;
            }
        }

        if (tilesLength % 3 == 0 || tilesLength % 4 == 0 || tilesLength % 5 == 0) {
            components = comps.getComponents(tyNamespace.ComponentType.Bao);

            if (components.length == 1) {
                var component = components[0];
                var remains = this.getRemains(tiles, component.tiles);

                if (remains.length == 0)
                    return component;
                else if (remains.length == 1) {
                    var sanYi = new tyNamespace.Component(tyNamespace.ComponentType.SanYi, tiles);
                    sanYi.setCore(component);

                    return sanYi;
                } else if (remains.length == 2) {
                    var duiComps = this.toGenerateFullComponents(remains);

                    if (duiComps.getComponents(tyNamespace.ComponentType.Dui).length == 1) {
                        var sanEr = new tyNamespace.Component(tyNamespace.ComponentType.SanEr, tiles);
                        sanEr.setCore(component);

                        return sanEr;
                    }
                }
            }

            components = comps.getComponents(tyNamespace.ComponentType.SanShun);

            if (components.length >= 1) {
                var component = components[0];
                var shunSize = component.tiles.length / 3;

                var remains = this.getRemains(tiles, component.tiles);

                if (remains.length == 0)
                    return component;
                else if (remains.length == shunSize) {
                    var sanShun = new tyNamespace.Component(tyNamespace.ComponentType.SanShun, tiles);
                    sanShun.setCore(component);

                    return sanShun;
                } else if (remains.length == 2 * shunSize) {
                    var duiComps = this.toGenerateFullComponents(remains);

                    var duiSize = duiComps.getComponents(tyNamespace.ComponentType.Dui).length;
                    var zhaSize = duiComps.getComponents(tyNamespace.ComponentType.Zha).length;

                    if (duiSize == shunSize || zhaSize * 2 + duiSize == shunSize) {
                        var sanShun = new tyNamespace.Component(tyNamespace.ComponentType.SanShun, tiles);
                        sanShun.setCore(component);

                        return sanShun;
                    }
                }
            }
        }

        return null;
    },
    
    getBiggerComponentFromTiles: function (tiles, component) {
    	var comps = this.generateAllComponents(tiles);

    	if (component == null) {
    		if (comps.components.length == 0) {
    			if (comps.singles.length == 0)
    				return null;

    			return new tyNamespace.Component(tyNamespace.ComponentType.Dan, tiles.slice(0, 1));
    		}

    		return comps.components[0];
    	}
    	
    	var type = component.type;
    	var compareTiles = component.tiles;
    	var compareSize = compareTiles.length;
    	var compareTile = compareTiles[0];
    	var compareCoreTiles = null;
    	
    	if (component.core != null) {
    		compareCoreTiles = component.core.tiles;
    		compareSize = compareCoreTiles.length;
    		compareTile = compareCoreTiles[0];
    		type = component.core.type;
    	}

//    	var biggerComps = comps.getBiggerComponents(type, compareTile.num, compareSize);

//    	cc.log("biggerComps.length" + biggerComps.length);

    	var result = null;

//    	if (biggerComps.length > 0)
//    		result = biggerComps[0];

    	if (result != null) {
    		if (result.type == tyNamespace.ComponentType.Zha && type != tyNamespace.ComponentType.Zha)
    			return result;

    		var compareRemains = [];
    		if (compareCoreTiles != null)
    			compareRemains = this.getRemains(compareTiles, compareCoreTiles);
    		else
    			compareCoreTiles = compareTiles;

    		var remains = this.getRemains(tiles, result.tiles);

    		cc.log("remains.length: " + remains.length + ",compareRemains.length:" + compareRemains.length + ",compareCoreTiles.length:" + compareCoreTiles.length + ",result.tiles.length: " + result.tiles.length);

    		if (remains.length < compareRemains.length || (compareCoreTiles.length > result.tiles.length && result.tiles[0].typeValue != tyNamespace.TileType.Wang))
    			return null;

    		if (compareRemains.length == 0)
    			return result;

    		if (type == tyNamespace.ComponentType.SanShun || tyNamespace.ComponentType.Bao) {
    			var shunSize = compareCoreTiles.length / 3;

    			var isDui = compareRemains.length / shunSize == 2;

    			cc.log("isDui: " + isDui + ",shunSize:" + shunSize);

    			if (isDui) {
    				var duiComps = this.generateAllComponents(remains).getComponents(tyNamespace.ComponentType.Dui);

    				if (duiComps.length < shunSize)
    					return null;
    				
    				for (var i = 0; i < shunSize; i++) {
    					result.tiles = result.tiles.concat(duiComps[i].tiles);
    				}
    			} else
    				for (var i = 0; i < shunSize; i++) {
    					result.tiles.push(remains[i]);
    				}
    		} else if (type == tyNamespace.ComponentType.Zha) {
    			if (compareRemains.length == 4) { //炸弹带2对
    				var duiComps = this.generateAllComponents(remains).getComponents(tyNamespace.ComponentType.Dui);

    				if (duiComps.length < 2)
    					return null;

    				for (var i = 0; i < 2; i++) {
    					result.tiles = result.tiles.concat(duiComps[i].tiles);
    				}
    			} else
	    			for (var i = 0; i < compareRemains.length; i++) {
	    				result.tiles.push(remains[i]);
	    			}
    		}
    	}

    	return result;
    },

    getBiggerComponent: function (player, component) {
        var tiles = player.handTiles;

        return this.getBiggerComponentFromTiles(tiles, component);
    },

    generateAllComponents: function (tiles) {
        var components = new tyNamespace.Components();

        this.forEachAddComponent(tiles, components);

        return components;
    },

    forEachAddComponent: function (tiles, components, tile) {
        var currentT = tiles[0];
        if (tile)
            currentT = tile;

        var noComp = true;

        var bomb = this.getBomb(tiles, currentT);
        if (bomb != null) {
            components.addComponent(bomb);

            noComp = false;
        }

        var shun = this.getShun(tiles, currentT, 3);

        if (shun.length >= 3) {
            var compType = tyNamespace.ComponentType.SanShun;
            if (shun.length == 3)
                compType = tyNamespace.ComponentType.Bao;

            components.addComponent(new tyNamespace.Component(compType, shun));

            noComp = false;
        }

        shun = this.getShun(tiles, currentT, 2);

        if (shun.length >= 2) {
            var compType = tyNamespace.ComponentType.Dui;
            if (shun.length != 2) {
                if (shun.length >= 6)
                    compType = tyNamespace.ComponentType.ErShun;
                else
                    shun = shun.slice(0, 2);
            }

            components.addComponent(new tyNamespace.Component(compType, shun));

            noComp = false;
        }

        shun = this.getShun(tiles, currentT);

        if (shun.length >= 5) {
            components.addComponent(new tyNamespace.Component(tyNamespace.ComponentType.Shun, shun));

            noComp = false;
        }

        if (noComp)
            components.singles.push(currentT);

        if (currentT.num == 14)
            return;

        var biggerTile = this.getBiggerCard(tiles, currentT.num);
        if (biggerTile != null)
            this.forEachAddComponent(tiles, components, biggerTile);
    },

    toGenerateFullComponents: function (tiles) {
        var components = new tyNamespace.Components();

        if (tiles != null && tiles.length > 0) {
            this.generateFullComponents(tiles, components);
        }

        return components;
    },

    generateFullComponents: function (tiles, components) {
        var tile = tiles[0];

        var bomb = this.getBomb(tiles, tile);
        if (bomb != null) {
            components.addComponent(bomb);

            var remains = this.getRemains(tiles, bomb.tiles);

            if (remains.length != 0)
                this.generateFullComponents(remains, components);

            return;
        }

        var shun = this.getShun(tiles, tile, 3);
        if (shun.length >= 3) {
            var type = tyNamespace.ComponentType.SanShun;
            if (shun.length == 3)
                type = tyNamespace.ComponentType.Bao;

            components.addComponent(new tyNamespace.Component(type, shun));

            var remains = this.getRemains(tiles, shun);

            if (remains.length != 0)
                this.generateFullComponents(remains, components);

            return;
        }

        shun = this.getShun(tiles, tile, 2);
        if (shun.length >= 2) {
            var type = tyNamespace.ComponentType.Dui;
            if (shun.length != 3) {
                if (shun.length >= 6)
                    type = tyNamespace.ComponentType.ErShun;
                else
                    shun = shun.slice(0, 2);
            }

            components.addComponent(new tyNamespace.Component(type, shun));

            var remains = this.getRemains(tiles, shun);

            if (remains.length != 0)
                this.generateFullComponents(remains, components);

            return;
        }

        shun = this.getShun(tiles, tile);
        if (shun.length >= 5) {
            var type = tyNamespace.ComponentType.Shun;

            components.addComponent(new tyNamespace.Component(type, shun));

            var remains = this.getRemains(tiles, shun);

            if (remains.length != 0)
                this.generateFullComponents(remains, components);

            return;
        }

        components.singles.push(tile);
        tiles.splice(0, 1);

        if (tiles.length > 0)
            this.generateFullComponents(tiles, components);
    },

    getBomb: function (tiles, tile) {
        var length = 4;
        if (tile.typeValue == tyNamespace.TileType.Wang)
            length = 2;

        var dui = this.getDui(tiles, tile, length);

        if (dui.length == length)
            return new tyNamespace.Component(tyNamespace.ComponentType.Zha, dui);

        return null;
    },

    getShun: function (tiles, tile, length) {
        if (!length)
            length = 1;

        var dui = this.getDui(tiles, tile, length);

        var shun = [];

        if (dui.length == length) {
            shun = shun.concat(dui);
            this.addNext(tiles, tile, shun, length);
        }

        return shun;
    },

    addNext: function (tiles, tile, shun, length) {
        var nextTile = this.getNextTile(tiles, tile);

        if (nextTile != null) {
            var dui = this.getDui(tiles, nextTile, length);

            if (dui.length == length) {
                for (var i = 0; i < length; i++) {
                    shun.push(dui[i]);
                }

                this.addNext(tiles, nextTile, shun, length);
            }
        }
    },

    getNextTile: function (tiles, tile) {
        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];

            if (currentT.num < 13 && currentT.num == tile.num + 1)
                return currentT;
        }

        return null;
    },

    getDui: function (tiles, tile, length) {
        if (length == null || length <= 0)
            length = 2;

        var dui = [];
        dui.push(tile);

        if (length <= 1)
            return dui;

        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];

            if (tile != currentT && (currentT.num == tile.num || (currentT.typeValue == tyNamespace.TileType.Wang && tile.typeValue == tyNamespace.TileType.Wang)))
                dui.push(currentT);

            if (dui.length == length)
                break;
        }

        return dui;
    },

    getRemains: function (tiles, compArray) {
        var afterRemove = [];
        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];
            if (!this.haveTileByHash(currentT, compArray)) {
                afterRemove.push(currentT);
            }
        }

        return afterRemove;
    },

    removeByHash: function (tiles, theTile) {
        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];
            if (theTile == currentT) {
                tiles.splice(i, 1);
                break;
            }
        }
    },

    haveTheTile: function (tile, tiles) {
        return this.getTileIndex(tile, tiles) >= 0;
    },

    haveTileByHash: function (tile, tiles) {
        return this.haveTileIndexByHash(tile, tiles) >= 0;
    },

    getTileIndex: function (tile, tiles) {
        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];

            if (currentT.num == tile.num && currentT.typeValue == tile.typeValue)
                return i;
        }

        return -1;
    },
    
    //获取牌
    getTile: function (tile, tiles) {
    	for (var i = 0; i < tiles.length; i++) {
    		var currentT = tiles[i];

    		if (currentT.num == tile.num && currentT.typeValue == tile.typeValue)
    			return currentT;
    	}

    	return null;
    },
    
    getBiggerCard: function (tiles, num) {
        if (num < 15) {
            for (var i = num + 1; i < 16; i++) {
                var biggerCard = this.getTheNumCard(tiles, i);
                if (biggerCard)
                    return biggerCard;
            }
        }

        return null;
    },

    getSmallerCard: function (tiles, num) {
        if (num > 1) {
            for (var i = num - 1; i > 0; i--) {
                var smallerCard = this.getTheNumCard(tiles, i);
                if (smallerCard)
                    return smallerCard;
            }
        }

        return null;
    },

    getTheNumCard: function (tiles, num) {
        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];

            if (currentT.num == num)
                return currentT;
        }

        return null;
    },

    haveTileIndexByHash: function (tile, tiles) {
        for (var i = 0; i < tiles.length; i++) {
            var currentT = tiles[i];

            if (currentT.id == tile.id)
                return i;
        }

        return -1;
    },

    getTileByNum: function (number) {
    	cc.log("number:" + number);

        if (number == 0x00)
            return null;

        var tileType = parseInt(number / 0x10);
        var tileNum = number % 0x10;

        cc.log("tileNum:" + tileNum + ",tileType:" + tileType);

        return new tyNamespace.Tile(tileType, tileNum);
    },

    getNumByTile: function (tile) {
        if (tile == null)
            return 0;

        var typeValue = tile.typeValue;
        var num = tile.num;

        return num + typeValue * 0x10;
    },

    getDzTileByNum: function (number) {
        if (number == 0x00)
            return null;

        var tileType = parseInt(number / 0x10);
        var tileNum = number % 0x10;

        return new dzpkNamespace.Tile(tileType, tileNum);
    },

    pushTile: function (tiles, tile) {
        if (!this.haveTheTile(tile, tiles))
            tiles.push(tile);
    },

});

gpNamespace.CardActions = new gpNamespace.CardActions();
